package Algoritmo;
import Grafica.Grafica;
import Grafica.Vertice;
import InterfazPantera.PanteraView;
/**
 *
 * @author robertoanzaldua
 * Clase que representa a un algoritmo
 */

public abstract class Algoritmo {

    ServiciosAlgoritmo interfaz;

    /**
     * Cadena que contendrá el desarrollo del algoritmo y usado para mostrarse en
     * el panel
     */
    protected StringBuilder desarrollo = new StringBuilder("\n\n");

    protected int clics  = 0;
    protected int clics0 = 0;
    protected int clics1 = 0;
    
    protected int vertAleat;
    protected int adyVertAleat;
    //Los vérices de la gráfica
    protected Vertice[]vertices;
    protected Grafica G;
    /**La gráfica actual mostada en el panel de graphviz
     * 
     */
    String graficaGV;
    String color = "#DA70D6";

    public Algoritmo(){
        super();
    }

    public Algoritmo(PanteraView interfaz,String nombre){
        G = interfaz.grafica();
        this.interfaz = interfaz;
        this.interfaz.dibuja();
        if(preCondiciones()){
            agregaPasos(nombre);
            cambiaPaso(0,0);
            borraDesarrollo();
        }else
            interfaz.regresaADiseño();
    }

    /**Nos regresa un arreglo con los pesos de las aristas
     *
     * @return int[][] el arreglo con los pesos.
     */
    public int[][] getPesos(){
        return interfaz.getPesos();
    }

    /**Borra lo contenido en el panel de desarrollo
     *
     */
    public void borraDesarrollo(){
        interfaz.borraDesarrollo();
        agregaADesarrollo("Desarrollo del algoritmo\n\n");
    }

    /**Regresa la gráfica actual en su representación de Graphviz
     *
     * @return String, una cadena con la representación de la gráfica
     * actual en el lenguaje de graphviz
     */
    public String generaGrafica(){
        return G.generaGrafica();
    }

    
    /**Regresa la gráfica actual de este algoritmo
     * 
     * @return <code>Grafica</code>
     */
    public Grafica getG(){
        return G;
    }

    /**
     *
     * @param G
     */
    public void setG(Grafica G){
        this.G = G;
    }



    /**Agrega los pasos correspondientes a este <code>algoritmo</code>
     *
     * @param nombre EL nombre de este <code>algoritmo</code>
     */
    public void agregaPasos(String nombre){
        interfaz.agregaPasos(nombre);
    }

    /**Agrega un suceso al desarrollo
     *
     * @param suceso La cadena que contiene el suceso
     */
    public void agregaADesarrollo(String suceso){
        interfaz.agregaADesarrollo(suceso);
    }


    /**Busca alguna arista disponible en las listas de adyacencias, si la
     * encuentra regresa el número asociado al vértice, si no, regresa -1
     *
     * @return int, el entero asociado al vértice o -1 en caso de no encontrar
     * aristas disponibles
     */
    protected int existenAristas(){
        return G.existenAristas();
    }


    /**Determina si el paso i se encuentra activo.
     *
     * @param i - El paso que se desea saber si está activo.
     * @return <code>boolean</code> que determina el estado del paso.
     */
    protected boolean esActual(int i){
        return interfaz.esActual(i);
    }

     /**Cambia la etiqueta del paso actual al siguiente.
     *
     * @param a El número de paso actual
     * @param b El número de paso al que se desea pasar
     */
    protected void cambiaPaso(int i, int j){
        interfaz.cambiaPaso(i ,j);
    }



    /**Desactiva el paso que se le pasa de parámetro
     *
     * @param a El número del paso a desactivar
     */
    public void desactiva(int a){
        interfaz.desactiva(a);
    }

    /**Marca una arista en la gráfica para distinguirla
     *
     * @param inf - Información relacionada con la arista a marcar, debe
     *              contener primero el color, y adicionalmente la dirección,
     *              la etiqueta, etc
     * @param dirigida - Nos dice si será dirigida la arista
     * @param vi - El vértice de donde sale la arista
     * @param vj - El vértice a donde llega
     */
    public void marcaArista(int vi, int vj, String inf, boolean dirigida){
        G.marcaArista(vi, vj, inf, dirigida);
    }

    /**Determina si un paso es nulo.
     *
     * @param p - El paso que se desea saber si es nulo.
     * @return <code>Boolean</code>, indica si el paso está marcado.
     */
    protected boolean nulo(int p){
       return interfaz.nulo(p);
    }


    /**Marca un vértice del color indicado.
     *
     * @param v - El número del vértice a marcar.
     * @param c - El color del vértice.
     */
    public void marcaVertice(int v, String c){
        interfaz.marcaVertice(v,c);
    }

    /**Envía un mensaje al usuario.
     *
     * @param mensaje - El mensaje a enviar.
     */
    public void enviaMensaje(String mensaje){
        interfaz.enviaMensaje(mensaje);
    }

    /**Regresa un número aleatorio que va desde 0 hasta <code>tope</code> - 1.
     *
     * @param tope
     * @return
     */
    protected int numA(int tope){
        return (int)(Math.random()*tope);
    }

    protected void dibuja(){
         // Pintamos en el panel la gráfica usando graphViz.
         graficaGV = G.generaGrafica();
         interfaz.dibuja(graficaGV);
    }


    /**Dibuja la gráfica con los grados de los vértices
     *
     */
     protected void dibujaGr(){
         // Pintamos en el panel la gráfica usando graphViz.
         graficaGV = G.generaGraficaGr();
         interfaz.dibuja(graficaGV);
    }

     /**Dibuja la gráfica con las distancias y los padres de cada vértice
      *
      * @param d
      * @param p
      */

     public void dibuja(int[]d,String[]p){
         graficaGV = G.generaGrafica(d, p);
         interfaz.dibuja(graficaGV);
     }

    public abstract void ejecutaPaso(); 

    protected boolean preCondiciones(){
        if(G.numV > 0)
            return true;

        enviaMensaje("La gráfica no contiene vértices, " +
                         "será regresado a la pantalla de diseño");
        return false;
    }

}
